#include "tcpsocketimpl.h"

int tcpsocket_eventcb(ioevstream_t* stream, short err, short what, _sock_t fd)
{
    rc_error(stream != NULL, S_ERROR);
    CTcpSocketImpl* tcpsock = (CTcpSocketImpl*)ioevstream_getctx(stream);

    return S_SUCCESS;
}
int tcpsocket_opencb(ioevstream_t* stream, short err, _sock_t fd)
{
    rc_error(stream != NULL, S_ERROR);
    CTcpSocketImpl* tcpsock = (CTcpSocketImpl*)ioevstream_getctx(stream);

    return S_SUCCESS;
}
int tcpsocket_readcb(ioevstream_t* stream, short err, buf_ptr ptr, buf_len len)
{
    rc_error(stream != NULL, S_ERROR);
    CTcpSocketImpl* tcpsock = (CTcpSocketImpl*)ioevstream_getctx(stream);

    return S_SUCCESS;
}
int tcpsocket_writecb(ioevstream_t* stream, short err, buf_ptr ptr, buf_len len)
{
    rc_error(stream != NULL, S_ERROR);
    CTcpSocketImpl* tcpsock = (CTcpSocketImpl*)ioevstream_getctx(stream);

    return S_SUCCESS;
}
CTcpSocketImpl::CTcpSocketImpl()
{
    m_sock = INVALID_SOCKET;
    m_stream = (ioevstream_t*)heap_malloc(sizeof(ioevstream_t));
}
CTcpSocketImpl::~CTcpSocketImpl()
{
    logi("CTcpSocketImpl::~CTcpSocketImpl");
}

HRESULT CTcpSocketImpl::CreateIoOperation(IAsynFrame* pIAsynFrame)
{
    HRESULT hr = S_OK;

    hr = pIAsynFrame->CreateIo(io_operation, (IBase**)&m_pReadOper);
    rc_error(hr == S_OK, E_FAIL);

    hr = pIAsynFrame->CreateIo(io_operation, (IBase**)&m_pWriteOper);
    rc_error(hr == S_OK, E_FAIL);

    hr = pIAsynFrame->CreateIo(io_operation, (IBase**)&m_pConnectOper);
    rc_error(hr == S_OK, E_FAIL);

    return S_OK;
}
HRESULT CTcpSocketImpl::BindEvloop(ioevloop_t* loop)
{
    ioevstream_init(m_stream, loop, INVALID_SOCKET);
    return S_OK;
}
HRESULT CTcpSocketImpl::CloseIo(UINT rw)
{
    return S_OK;
}
HRESULT CTcpSocketImpl::BindIo()
{
    rc_error(m_sock != INVALID_SOCKET, E_FAIL);
    return S_OK;
}
HRESULT CTcpSocketImpl::OpenIo()
{
    return S_OK;
}
HRESULT CTcpSocketImpl::BindEvent(IBase* pSocketEvent)
{
    return S_OK;
}
HRESULT CTcpSocketImpl::UnBindEvent()
{
    return S_OK;
}
HRESULT CTcpSocketImpl::CreateSock()
{
    HRESULT hr = S_OK;
    m_sock = INVALID_SOCKET;
    m_sock = _createsock(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    rc_error(m_sock != INVALID_SOCKET, E_FAIL);

    set_blocking(m_sock, 1);
    ioevstream_assign(m_stream, m_sock);
    ioevstream_setctx(m_stream, this);
    ioevstream_seteventcb(m_stream, tcpsocket_eventcb);
    ioevstream_setreadcb(m_stream, tcpsocket_readcb);
    ioevstream_setwritecb(m_stream, tcpsocket_writecb);

    return hr;
}
HRESULT CTcpSocketImpl::CloseSock()
{
    HRESULT hr = S_OK;

    rc_error(IsOpen() == S_OK, S_OK);
    rc_error(m_sock != INVALID_SOCKET, E_FAIL);
    ioevstream_uninit(m_stream);
    // TODO: this is error
    _closesock(m_sock);
    m_sock = INVALID_SOCKET;

    return hr;
}
HRESULT CTcpSocketImpl::IsOpen()
{
    return S_OK;
}
HRESULT CTcpSocketImpl::AttachSock(_sock_t sock)
{
    rc_error(sock != INVALID_SOCKET, E_FAIL);
    m_sock = sock;

    set_blocking(m_sock, 1);
    ioevstream_assign(m_stream, m_sock);
    ioevstream_setctx(m_stream, this);
    ioevstream_seteventcb(m_stream, tcpsocket_eventcb);
    ioevstream_setreadcb(m_stream, tcpsocket_readcb);
    ioevstream_setwritecb(m_stream, tcpsocket_writecb);

    return S_OK;
}
_sock_t CTcpSocketImpl::DetachSock()
{
    _sock_t sock;
    sock = m_sock;
    m_sock = INVALID_SOCKET;
    return sock;
}
_sock_t CTcpSocketImpl::GetSock()
{
    return m_sock;
}
HRESULT CTcpSocketImpl::GetReadOperation(IID id, IBase** pBase)
{
    rc_error(m_pReadOper.m_p != NULL, E_FAIL);
    return this->m_pReadOper->QueryInterface(id, (void**)pBase);
}
HRESULT CTcpSocketImpl::GetWriteOperation(IID id, IBase** pBase)
{
    rc_error(m_pWriteOper.m_p != NULL, E_FAIL);
    return this->m_pWriteOper->QueryInterface(id, (void**)pBase);
}
HRESULT CTcpSocketImpl::ReadIo(ULONG pos, ULONG size, crtid event, int tm)
{
    int rc = S_SUCCESS;

    return (S_SUCCESS == rc) ? S_OK : E_FAIL;
}
HRESULT CTcpSocketImpl::WriteIo(ULONG pos, ULONG size, crtid cid, int tm)
{
    int rc = S_SUCCESS;

    // hr = pBase->QueryInterface(IID_IOperation, (void**)&m_pOperation);
    // rc_error(hr == S_OK, E_FAIL)

    // this->ctx.data = pBase;
    // this->ctx.event = event;

    // hr = m_pOperation->GetPtr(&this->ctx.wptr);
    // rc_error(this->ctx.wptr != NULL, E_FAIL)
    // rc_error(hr == S_OK, E_FAIL)

    // hr = m_pOperation->GetExpect(&this->ctx.wlen);
    // rc_error(hr == S_OK, E_FAIL)

    // rc = async_write(this->ctx.wptr, this->ctx.wlen, this);

    return (S_SUCCESS == rc) ? S_OK : E_FAIL;
}
HRESULT CTcpSocketImpl::ConnectIo(NET_ADDR addr, NET_PORT port, crtid event, int tm)
{
    rc_error(m_sock != INVALID_SOCKET, E_FAIL);
    rc_error(addr != NULL, E_FAIL);
    rc_error(port != INVALID_NET_PORT, E_FAIL);
    rc_error(m_stream.m_p != INVALID_NET_PORT, E_FAIL);

    int rc = S_SUCCESS;

    rc = ioevstream_connectsock(m_stream, addr, port, tm);

    return (rc == S_SUCCESS) ? S_OK : E_FAIL;
}
